/* 
 * File:   ConfigurationFile.cpp
 * Copyright (C) 2008, 2009
 *		Sergio Padrino Recio (PadrinatoR)
 *		DOC
 *		Joseba Saenz de Navarrete Royo
 *		Nacho
 *
 * Created on 8 de septiembre de 2008, 20:34
 *
 * This file is part of BombProject.
 * 
 * BombProject is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
   
 * BombProject is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with BombProject.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "ConfigurationFile.h"

#include <stdio.h>
#include <SDL/SDL_rwops.h>

/**
 * Constructor.
 */
ConfigurationFile::ConfigurationFile(){
}

/**
 * Destructor.
 */
ConfigurationFile::~ConfigurationFile(){
}

/**
 * Loads a configuration file and parses it.
 * @param filename Configuration file name.
 * @return false if there was an error.
 */
bool ConfigurationFile::loadFile(string filename){
	SDL_RWops *file = SDL_RWFromFile(filename.c_str(), "r");
	if (file == NULL) return false;
	
	SDL_RWseek(file, 0, SEEK_END);
	
	int fileSize = SDL_RWtell(file);
	
	SDL_RWseek(file, 0, 0);
	
	char *buffer = new char[fileSize];
	
	if(SDL_RWread(file, buffer, 1, fileSize) != fileSize){
		SDL_RWclose(file);
		delete buffer;
		
		return false;
	}
	
	SDL_RWclose(file);
	
	parse(string(buffer, fileSize));
	
	delete buffer;
	
	return true;
}

	//TODO: getInteger, getFloat, getPoint?, getLoquesea_XD

/**
 * Parses the configuration file.
 * @param data Text to be parsed.
 */
void ConfigurationFile::parse(string data){
	string line = "", variable = "", value = "";
	size_t equal_pos = -1, endline_pos = 0, offset = 0;
	
	while(endline_pos != -1 && offset != -1) {
		endline_pos = data.find_first_of("\r\n", offset);
		
		if(endline_pos == -1)
			line = data.substr(offset, -1);
		else
			line = data.substr(offset, endline_pos - offset);
		
		equal_pos = line.find('=');
		
		if(equal_pos != -1){
			variable = line.substr(0, equal_pos);
			value = line.substr(equal_pos + 1, line.length() - equal_pos - 1);
			
			try{
				if(variable == "")
					fprintf(stderr, "ConfigurationFile::Parse - Variable without name\n");
				else
					variablesList[variable] = value;
			}catch(...){
				fprintf(stderr, "ConfigurationFile::Parse - Duplicated variable '%s'\n", variable.c_str());
			}
		}
		
		offset = data.find_first_not_of("\r\n", endline_pos);
	}
}

/**
 * Returns an integer value from a variable.
 * @param variable Variable's name.
 * @param default_value Value to be returned if the variable wasn't found.
 * @return Variable's value.
 */
int ConfigurationFile::getInteger(string variable, int default_value){
	if(variablesList.find(variable) != variablesList.end())
		return atoi(variablesList[variable].c_str());
	else
		return default_value;
}

/**
 * Returns a string value from a variable.
 * @param variable Variable's name.
 * @param default_value Value to be returned if the variable wasn't found.
 * @return Variable's value.
 */
string ConfigurationFile::getString(string variable, string default_value){
	if(variablesList.find(variable) != variablesList.end())
		return variablesList[variable];
	else
		return default_value;
}

/**
 * Returns a list of integers from a variable.
 * @param variable Variable's name.
 * @param separator Character used to separate two elements in the list.
 * @return Variable's value.
 */
vector<int> ConfigurationFile::getIntegerList(string variable, char separator){
	vector<int> integer_list;
	
	integer_list.clear();
	
	if(variablesList.find(variable) != variablesList.end()){
		string value = variablesList[variable];
		string number = "";
		size_t offset = 0, pos = 0;
		
		while(offset < value.length()){
			pos = value.find(separator, offset);
			if(pos != -1)
				number = value.substr(offset, pos - offset);
			else
				number = value.substr(offset, -1);

			integer_list.push_back(atoi(number.c_str()));
			
			if(pos == -1) break;
			
			offset = pos+1;
		}
	}
	
	return integer_list;
}

/**
 * Returns a button's information from a variable.
 * @param variable Variable's name.
 * @param info Structure to store the button's information.
 * @return true if it was succesful, false if not.
 */
bool ConfigurationFile::getButtonInfo(string variable, DeviceButtonInfo& info) {
	vector<int> integer_list = getIntegerList(variable);

	if(integer_list.size() != 3)
		return false;

	info.button_code = integer_list[0];
	info.device_type = (DeviceType) integer_list[1];
	info.device_index = integer_list[2];

	return true;
}
